package com.yx.crawler.analyse;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public final class SimilarityAnalyse {
	private final static IdfManager idfManager=new IdfManager();
	private static Double tatalTF_IDFPercent=0.6;
	public SimilarityAnalyse(){		
	}
	public static Double getTatalTF_IDFPercent() {
		return tatalTF_IDFPercent;
	}
	public static void setTatalTF_IDFPercent(Double tatalTF_IDFPercent) {
		SimilarityAnalyse.tatalTF_IDFPercent = tatalTF_IDFPercent;
	}
	public static void addIdfDocument(int id,String content){
		idfManager.addDocument(id,content);
	}
	public static int getLastIdfDocumentId(){
		return idfManager.getLastDoucumentId();
	}
	public static void saveIdfWords()throws Exception{
		idfManager.saveTo();
	}
	public static SimilarityModel buildModel(String key,String modelText,String discription,Double leastCosValue){
		LinkedHashMap<String, Double> model=ChineseWordSpliter.tf_idfSplit(modelText, idfManager,tatalTF_IDFPercent);
		return new SimilarityModel(key,model,discription,leastCosValue);
	}
	public static LinkedHashMap<String, Double> tf_idfSplit(String text){
		return ChineseWordSpliter.tf_idfSplit(text, idfManager,tatalTF_IDFPercent);
	}
	public List<Similarity> analyse(List<SimilarityModel> models,String text){
		List<Similarity> similaritys=new ArrayList<Similarity>();
		if(text==null||models==null||models.size()<1)return similaritys;
		Map<String, Double> contentTfMap =ChineseWordSpliter.tf_idfSplit(text, idfManager,tatalTF_IDFPercent);
		for(SimilarityModel model:models){
			Double degree=cos(contentTfMap,model.model(),idfManager);
			if(degree<=model.leastValue())continue;
			Similarity similarity=new Similarity(model.key(),model.discription(),degree);
			similaritys.add(similarity);
		}
		Collections.sort(similaritys, new Comparator<Similarity>() {
            public int compare(Similarity arg0, Similarity arg1) {
                return arg1.value().compareTo(arg0.value());
            }
        });
		return similaritys;
	}
	public class Similarity{
		private String key,discription;		
		private Double value;
		private Similarity(String key,String discription,Double value){
			this.key=key;
			this.discription=discription;
			this.value=value;
		}
		public String key() {
			return key;
		}
		public String discription() {
			return discription;
		}
		public Double value() {
			return value;
		}
	}
	
	private static Double cos(Map<String, Double> contentTfMap, LinkedHashMap<String, Double> model,IdfManager idfManager) {
		try {
			Map<String, Double> firstTfMap =contentTfMap;// ChineseWordSpliter.tf_idfSplit(first, idfManager,leastTF_IDFValue);
			Map<String, Double> secondTfMap = model;
			if (firstTfMap.size() < secondTfMap.size()) {
				Map<String, Double> temp = firstTfMap;
				firstTfMap = secondTfMap;
				secondTfMap = temp;
			}
			return calculateCos((LinkedHashMap<String, Double>) firstTfMap,
					(LinkedHashMap<String, Double>) secondTfMap);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return 0d;
	}

	private static Double calculateCos(LinkedHashMap<String, Double> first, LinkedHashMap<String, Double> second) {
		List<Map.Entry<String, Double>> firstList = new ArrayList<Map.Entry<String, Double>>(first.entrySet());
		List<Map.Entry<String, Double>> secondList = new ArrayList<Map.Entry<String, Double>>(second.entrySet());
		// 计算相似度
		double vectorFirstModulo = 0.00;// 向量1的模
		double vectorSecondModulo = 0.00;// 向量2的模
		double vectorProduct = 0.00; // 向量积
		int secondSize = second.size();
		for (int i = 0; i < firstList.size(); i++) {
			if (i < secondSize) {
				vectorSecondModulo += secondList.get(i).getValue().doubleValue()
						* secondList.get(i).getValue().doubleValue();
				vectorProduct += firstList.get(i).getValue().doubleValue() * secondList.get(i).getValue().doubleValue();
			}
			vectorFirstModulo += firstList.get(i).getValue().doubleValue() * firstList.get(i).getValue().doubleValue();
		}
		return vectorProduct / (Math.sqrt(vectorFirstModulo) * Math.sqrt(vectorSecondModulo));
	}
}
